package com.coder.common.aop;

import com.coder.common.annotation.MyTransactional;
import com.coder.common.util.DatabaseUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;

@Aspect
@Component
public class Aop {

    @Autowired
    private DatabaseUtil databaseUtil;

    @Pointcut("@annotation(com.coder.common.annotation.MyTransactional)")
    public void pointCutAnnotation(){}

    @Around("pointCutAnnotation()")
    public Object interceptTransactional(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Annotation annotation = signature.getMethod().getDeclaredAnnotation(MyTransactional.class);
        if(annotation == null){
            return point.proceed();
        }

        databaseUtil.begin();
        Object proceed = point.proceed();
        databaseUtil.commit(databaseUtil.getTransactionStatus());
        return proceed;
    }

    @AfterThrowing("pointCutAnnotation()")
    public void rollback(JoinPoint point){
        MethodSignature signature = (MethodSignature) point.getSignature();
        Annotation annotation = signature.getMethod().getDeclaredAnnotation(MyTransactional.class);
        if(annotation != null){
            databaseUtil.rollback(databaseUtil.getTransactionStatus());
        }
    }
}
